Imports KellermanSoftware.SharpZipWrapper
Imports ErrorHandling

Public Class frmMain
    Private Const DESKTOP_CREATEMENU As Int32 = &H4&
    Private Const DESKTOP_CREATEWINDOW As Int32 = &H2&
    Private Const DESKTOP_ENUMERATE As Int32 = &H40&
    Private Const DESKTOP_HOOKCONTROL As Int32 = &H8&
    Private Const DESKTOP_READOBJECTS As Int32 = &H1&
    Private Const DESKTOP_SWITCHDESKTOP As Int32 = &H100&
    Private Const DESKTOP_WRITEOBJECTS As Int32 = &H80&
    Private Const GENERIC_WRITE As Int32 = &H40000000
    Private Const HWND_BROADCAST As Int32 = &HFFFF&
    Private Const WM_HOTKEY As Int32 = &H312
    Private Const MOD_ALT As Int32 = &H1
    Private Const MOD_CONTROL As Int32 = &H2
    Private Const VK_DELETE As Int32 = &H2E
    Private Const UOI_NAME As Int32 = 2
    Private Declare Function OpenDesktop Lib "user32" Alias "OpenDesktopA" (ByVal lpszDesktop As String, ByVal dwFlags As Int32, ByVal fInherit As Boolean, ByVal dwDesiredAccess As Int32) As Int32
    Private Declare Function CloseDesktop Lib "user32" (ByVal hDesktop As Int32) As Int32
    Private Declare Function SwitchDesktop Lib "user32" (ByVal hDesktop As Int32) As Int32

    Public clients As Object
    Public rebootReminderActive As Boolean = False

    'this tells me how much to multiple timer numbers by
    'ie: 1000 means turn everything into seconds (for testing)
    'ie: 60000 means turn everything into minutes (production)
    Public Const timerMultiplier As Integer = 60000

    ' Exit Windows Constants
    Const EWX_LOGOFF As Integer = &H0
    Const EWX_SHUTDOWN As Integer = &H1
    Const EWX_REBOOT As Integer = &H2
    Const EWX_FORCE As Integer = &H4
    Const EWX_POWEROFF As Integer = &H8
    Const EWX_FORCEIFHUNG As Integer = &H10

    Public tmrCheckIn As System.Threading.Timer
    Public tmrrebootreminder As System.Threading.Timer

    Public Structure clientStateType
        Dim rebootPending As Boolean
        Dim version As String
        Dim policy As policyType
    End Structure
    Public clientGUID As String = "0"
    Public net As New ernNetwork.Client
    Public timerWentOff As Boolean
    Public clientRestarted As Boolean = False
    'Public thrClientLoop As New Threading.Thread(AddressOf clientLoop)
    Public clientState As clientStateType
    Public lastCheckInTime As String

    Declare Unicode Function NetRenameMachineInDomain Lib "netapi32.dll" (ByVal lpServer As String, ByVal lpNewMachineName As String, ByVal lpAccount As String, ByVal lpPassword As String, ByVal fRenameOptions As Integer) As Integer
    Declare Function SetComputerNameEx Lib "kernel32.dll" Alias "SetComputerNameExA" (ByVal NameType As cNameType, ByVal lpBuffer As String) As Long
    Enum cNameType 'COMPUTER_NAME_FORMAT
        ComputerNameNetBIOS '0
        ComputerNameDnsHostname
        ComputerNameDnsDomain
        ComputerNameDnsFullyQualified
        ComputerNamePhysicalNetBIOS
        ComputerNamePhysicalDnsHostname
        ComputerNamePhysicalDnsDomain
        ComputerNamePhysicalDnsFullyQualified '7
        ComputerNameMax
    End Enum

    Sub exitClient()
        'modXML.writeConfiguration()
        'alreadyRestartedClient = True
        Application.Exit()
    End Sub

    Sub OnShuttingdown(ByVal sender As Object, ByVal e As Microsoft.Win32.SessionEndingEventArgs)
        exitClient()
    End Sub

    Sub OnShutdown(ByVal sender As Object, ByVal e As Microsoft.Win32.SessionEndedEventArgs)
        exitClient()
    End Sub

    Private Sub frmMain_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
        exitClient()
    End Sub

    Private Sub frmMain_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Me.Hide()

        Threading.Thread.CurrentThread.Name = "frmmain"

        If Not Diagnostics.Debugger.IsAttached Then
            UnhandledExceptionManager.DisplayDialog = True
            UnhandledExceptionManager.EmailScreenshot = False
            UnhandledExceptionManager.KillAppOnException = True
            UnhandledExceptionManager.ScreenshotImageFormat = Drawing.Imaging.ImageFormat.Jpeg
            UnhandledExceptionManager.SendEmail = False
            UnhandledExceptionManager.TakeScreenshot = False
            UnhandledExceptionManager.AddHandler()
        End If

        'trap logoff and shutdown events seperate from the form closing
        'so the system can shutdown
        AddHandler Microsoft.Win32.SystemEvents.SessionEnding, AddressOf OnShuttingdown
        AddHandler Microsoft.Win32.SystemEvents.SessionEnded, AddressOf OnShutdown

        ernClientVersion = Diagnostics.FileVersionInfo.GetVersionInfo(Application.ExecutablePath).FileVersion
        If ernClientVersion = "" Then ernClientVersion = "0.1.9.8"
        'if we are running the client from the IDE then say we are 
        'the highest version possible to avoid getting any AutoUpdates applied to us
        If Diagnostics.Debugger.IsAttached Then ernClientVersion = "99.99.99.99"
        lastCheckInTime = Today.ToString

        CheckForIllegalCrossThreadCalls = False
        iconSystray.ShowBalloonTip(1000, "ERN Client", "ERN Client is starting", ToolTipIcon.Info)
        launchClient()
    End Sub

    Public Sub launchClient()
        Dim msg As protocol
        Dim lastKnownVersion As String

        modXML.readConfiguration()
        'this is used to determine if the timer (for checkin) has gone off and if we are working on that
        timerWentOff = False

        tmrCheckIn = New System.Threading.Timer(New System.Threading.TimerCallback(AddressOf tmrCheckIn_Tick))
        tmrrebootreminder = New System.Threading.Timer(New System.Threading.TimerCallback(AddressOf tmrRebootReminder_Tick))

        clientState.rebootPending = False
        clientState.version = ernClientVersion
        frmUI.lblClientVersion.Text = ernClientVersion
        frmUI.lblLastCheckedInTime.Text = lastCheckInTime
        'remove files that are downloaded
        cleanupWorkingDirectories()

        'if no server was found in the config file then broadcast and look for one
        If net.getServerName = "localhost" Then
            Dim broadcastEP As New System.Net.IPEndPoint(System.Net.IPAddress.Broadcast, ern_broadcastPort)
            Dim udpClient As New Net.Sockets.UdpClient()
            Dim udpMessage As Byte()
            Dim response As String()

            udpClient.EnableBroadcast = True
            udpMessage = System.Text.Encoding.ASCII.GetBytes(ernClientVersion)
            Try
                udpClient.Send(udpMessage, udpMessage.Length, broadcastEP)
                udpClient.Client.ReceiveTimeout = 30
                response = Split(System.Text.Encoding.ASCII.GetString(udpClient.Receive(broadcastEP)), "::")
                net.setServerName(response(0))
            Catch
                'they are probably only have loopback interface - so use localhost
                net.setServerName("localhost")
            End Try
        End If

        'connect to the server
        While Not net.connect()
            Application.DoEvents()
        End While

        'do initial check in
        msg.type = protocolType.C_computerName
        msg.message = gatherCheckinData()
        net.sendMessage(msg)
        net.getMessage(msg)
        clientGUID = Split(msg.message, "::")(0)
        lastKnownVersion = Split(msg.message, "::")(1)
        modXML.writeConfiguration()
        msg.message = 1
        msg.type = protocolType.C_getPolicy
        net.sendMessage(msg)
        net.getMessage(msg)
        clientState.policy = applyPolicy(msg.message)
        frmUI.lblLastCheckedInTime.Text = Now.ToString("M/d/yyyy h:mm") & LCase(Now.ToString("tt"))
        'thrClientLoop.IsBackground = True

        'check to see if the client was recently updated
        If lastKnownVersion <> clientState.version Then
            Dim logLine As String = ""
            Dim auLog As IO.StreamReader

            If IO.File.Exists(Application.StartupPath & "\au.log") Then
                auLog = New IO.StreamReader(Application.StartupPath & "\au.log")
                While Not auLog.EndOfStream
                    logLine = auLog.ReadLine()
                End While
            Else
                logLine = "0::2007-01-01 12:00::0::0::0::Log file is missing"
            End If

            msg.type = protocolType.C_clientUpdated
            msg.message = logLine
            net.sendMessage(msg)
        End If

        'thrClientLoop.Start()
        clientLoop()
    End Sub

    Private Function applyPolicy(ByVal polStr As String) As policyType
        Dim polArray() As String
        Dim pol As policyType

        polArray = Split(polStr, ControlChars.NullChar)
        pol.id = polArray(0)
        pol.name = polArray(1)
        pol.checkInTime = polArray(2)
        pol.rebootPolicy.everyFewMinutes = polArray(3)
        pol.rebootPolicy.time1 = polArray(4)
        pol.rebootPolicy.useTime1 = polArray(5)
        pol.rebootPolicy.time2 = polArray(6)
        pol.rebootPolicy.useTime2 = polArray(7)
        pol.rebootPolicy.time3 = polArray(8)
        pol.rebootPolicy.useTime3 = polArray(9)
        pol.rebootPolicy.rebootSchedule = polArray(10)
        pol.rebootPolicy.scheduledRebootDay = polArray(11)
        tmrCheckIn.Change((pol.checkInTime * timerMultiplier), (pol.checkInTime * timerMultiplier))
        pol.auPolicy.enabled = polArray(12)
        pol.auPolicy.day = polArray(13)
        pol.auPolicy.time = polArray(14)

        Return pol
    End Function

    Public Sub clientLoop()
        Dim msg As protocol

        While True
            msg.message = ""
            msg.type = protocolType.BLANK
            'MsgBox(net.hasData)
            If Not timerWentOff Then
                If net.hasData Then
                    'tmrCheckIn.Change(System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite)
                    net.getMessage(msg)
                    handleMessage(msg)
                    'tmrCheckIn.Change((clientState.policy.checkInTime * timerMultiplier), (clientState.policy.checkInTime * timerMultiplier))
                End If
            End If
            Threading.Thread.Sleep(1000)
            frmUI.lblLastCheckedInTime.Text = lastCheckInTime
            Application.DoEvents()
        End While
    End Sub

    Private Sub handleMessage(ByVal msg As protocol)
        Dim item As String
        Dim info() As String = Nothing

        If msg.type = protocolType.S_rebootReminder Then
            'showRebootReminder()
            setRebootReminder()
            msg.type = protocolType.C_rebootReminder
            msg.message = "OK"
            net.sendMessage(msg)
        ElseIf msg.type = protocolType.S_heartbeat Then
            msg.type = protocolType.C_heartbeat
            msg.message = "pong"
            net.sendMessage(msg)
        ElseIf msg.type = protocolType.S_renameClient Then
            'I assume the user that the ERN client is running as can rename the computer
            item = msg.message
            msg.message = NetRenameMachineInDomain(System.Environment.MachineName, item, "", "", 2)
            If msg.message = "2692" Then
                msg.message = SetComputerNameEx(cNameType.ComputerNamePhysicalNetBIOS, item)
                msg.message = msg.message * SetComputerNameEx(cNameType.ComputerNamePhysicalDnsHostname, item)
                If msg.message > 0 Then msg.message = "0" Else msg.message = "-1"
            End If
            msg.type = protocolType.C_renameClient
            net.sendMessage(msg)
        ElseIf msg.type = protocolType.S_scheduledRebootReminder Then
            showScheduledRebootReminder()
            msg.type = protocolType.C_scheduledRebootReminder
            msg.message = "OK"
            net.sendMessage(msg)
        ElseIf msg.type = protocolType.S_forceClientReboot Then
            Dim tmrForcedReboot15 As New System.Threading.Timer(New System.Threading.TimerCallback(AddressOf tmrForcedRebootReminder15_Tick))
            Dim tmrForcedReboot5 As New System.Threading.Timer(New System.Threading.TimerCallback(AddressOf tmrForcedRebootReminder5_Tick))
            Dim tmrForcedReboot2 As New System.Threading.Timer(New System.Threading.TimerCallback(AddressOf tmrForcedRebootReminder2_Tick))
            Dim tmrForceReboot As New System.Threading.Timer(New System.Threading.TimerCallback(AddressOf tmrForceReboot_Tick))

            If 60000 * 20 < msg.message Then
                'display warning
                MsgBox("You computer is being forced to restart.  Please close any open documents or programs.  Your computer will restart in about " & msg.message / 60000 & " minutes.")
                'set timer to start at 15
                tmrForcedReboot15.Change(CType((msg.message - (60000 * 15)), Long), Threading.Timeout.Infinite)
                'set timer for 5
                tmrForcedReboot5.Change(CType((msg.message - (60000 * 5)), Long), Threading.Timeout.Infinite)
                'set timer for 2
                tmrForcedReboot2.Change(CType((msg.message - (60000 * 2)), Long), Threading.Timeout.Infinite)
            ElseIf 60000 * 8 < msg.message Then
                'display warning
                MsgBox("You computer is being forced to restart.  Please close any open documents or programs.  Your computer will restart in about " & msg.message / 60000 & " minutes.")
                'set timer for 5
                tmrForcedReboot5.Change(CType((msg.message - (60000 * 5)), Long), Threading.Timeout.Infinite)
                'set timer for 2
                tmrForcedReboot2.Change(CType((msg.message - (60000 * 2)), Long), Threading.Timeout.Infinite)
            ElseIf 60000 * 4 < msg.message Then
                'display warning
                MsgBox("You computer is being forced to restart.  Please close any open documents or programs.  Your computer will restart in about " & msg.message / 60000 & " minutes.")
                'set timer for 2
                tmrForcedReboot2.Change(CType((msg.message - (60000 * 2)), Long), Threading.Timeout.Infinite)
            Else
                'display warning and nothing else
                MsgBox("You computer is being forced to restart.  Please close any open documents or programs.  Your computer will restart in about " & msg.message / 60000 & " minutes.  This is your first and final warning!")
            End If
            tmrForceReboot.Change(CType(msg.message, Long), Threading.Timeout.Infinite)
        ElseIf msg.type = protocolType.S_sendAU Then
            info = Split(msg.message, "::")
            msg.message = "1"
            msg.type = protocolType.C_downloadAU
            net.sendMessage(msg)
            net.getFile(filesLocationDownloads & info(0), info(2))
            If MD5Hash(filesLocationDownloads & info(0)) <> info(1) Then
                MsgBox("Error: Autoupdate file transfer failed - MD5 hash mismatch")
            Else
                autoUpdateClient(info)
            End If
        End If
    End Sub

    Private Sub tmrForceReboot_Tick(ByVal state As Object)
        Dim uFlags As Long
        Dim result As Int32 = 0
        Dim scope As New Management.ManagementScope("\\localhost\root\cimv2")

        scope.Options.EnablePrivileges = True
        scope.Connect()
        Dim oq As New System.Management.ObjectQuery("SELECT * FROM Win32_OperatingSystem")
        Dim query1 As New Management.ManagementObjectSearcher(scope, oq)
        Dim queryCollection1 As Management.ManagementObjectCollection = query1.Get()
        Dim mo As Management.ManagementObject

        'try for 2 minutes to reboot the nice way
        uFlags = EWX_REBOOT
        For Each mo In queryCollection1
            Dim ss As String() = {uFlags, "0"}
            mo.InvokeMethod("Win32Shutdown", ss)
        Next
        Threading.Thread.Sleep(2 * timerMultiplier)
        'ok, you wanna play rough?  try for 2 more minutes to make them reboot
        uFlags = uFlags Or EWX_FORCE
        For Each mo In queryCollection1
            Dim ss As String() = {uFlags, "0"}
            mo.InvokeMethod("Win32Shutdown", ss)
        Next
        Threading.Thread.Sleep(2 * timerMultiplier)
        'ok no more mr. nice guy - reboot now!
        uFlags = uFlags Or EWX_FORCEIFHUNG
        For Each mo In queryCollection1
            Dim ss As String() = {uFlags, "0"}
            mo.InvokeMethod("Win32Shutdown", ss)
        Next
    End Sub

    Private Sub tmrForcedRebootReminder15_Tick(ByVal state As Object)
        MsgBox("You computer is being forced to restart.  Please close any open documents or programs.  Your computer will restart in about 15 minutes")
    End Sub

    Private Sub tmrForcedRebootReminder5_Tick(ByVal state As Object)
        MsgBox("You computer is being forced to restart.  Please close any open documents or programs.  Your computer will restart in about 5 minutes")
    End Sub

    Private Sub tmrForcedRebootReminder2_Tick(ByVal state As Object)
        MsgBox("You computer is being forced to restart.  Please close any open documents or programs.  Your computer will restart in about 2 minutes")
    End Sub

    Sub setRebootReminder()
        If clientState.policy.rebootPolicy.rebootSchedule = rebootScheduleType.everyFewMinutes Then
            tmrrebootreminder.Change((timerMultiplier * clientState.policy.rebootPolicy.everyFewMinutes), (timerMultiplier * clientState.policy.rebootPolicy.everyFewMinutes))
        ElseIf clientState.policy.rebootPolicy.rebootSchedule = rebootScheduleType.threeTimesADay Then
            Dim nowTimer As Date
            nowTimer = Date.Parse("7/5/2007 " & Now.Hour & ":" & Now.Minute)

            If clientState.policy.rebootPolicy.useTime1 And clientState.policy.rebootPolicy.time1 > nowTimer Then
                'use time1
                tmrrebootreminder.Change((clientState.policy.rebootPolicy.time1 - nowTimer), TimeSpan.Zero)
            ElseIf clientState.policy.rebootPolicy.useTime2 And clientState.policy.rebootPolicy.time2 > nowTimer Then
                'use time2
                tmrrebootreminder.Change((clientState.policy.rebootPolicy.time2 - nowTimer), TimeSpan.Zero)
            ElseIf clientState.policy.rebootPolicy.useTime3 And clientState.policy.rebootPolicy.time3 > nowTimer Then
                'use time3
                tmrrebootreminder.Change((clientState.policy.rebootPolicy.time3 - nowTimer), TimeSpan.Zero)
            Else
                'use time1
                tmrrebootreminder.Change((clientState.policy.rebootPolicy.time1.AddDays(1) - nowTimer), TimeSpan.Zero)
            End If
        End If
    End Sub

    Private Sub tmrCheckIn_Tick(ByVal state As Object)
        Dim msg As protocol

        timerWentOff = True

        msg.type = protocolType.C_checkIn
        msg.message = gatherCheckinData()
        net.sendMessage(msg)
        net.getMessage(msg)
        While msg.type <> protocolType.S_policy
            handleMessage(msg)
            net.getMessage(msg)
        End While

        applyPolicy(msg.message)
        lastCheckInTime = Now.ToString("M/d/yyyy h:mm") & LCase(Now.ToString("tt"))
        frmUI.lblLastCheckedInTime.Text = lastCheckInTime
        frmUI.Activate()

        timerWentOff = False
    End Sub

    Private Function gatherCheckinData() As String
        Dim returner As String = ""
        Dim searchCS As New Management.ManagementObjectSearcher("Select * from Win32_ComputerSystem")
        Dim searchSE As New Management.ManagementObjectSearcher("Select * from Win32_SystemEnclosure")
        Dim searchP As New Management.ManagementObjectSearcher("Select * from Win32_Process")
        Dim searchCPU As New Management.ManagementObjectSearcher("Select * from Win32_Processor")
        Dim searchOS As New Management.ManagementObjectSearcher("Select * from Win32_OperatingSystem")
        Dim searchUpTime As New Management.ManagementObjectSearcher("Select * from Win32_PerfRawData_PerfOS_System")
        Dim searchHD As New Management.ManagementObjectSearcher("Select * from Win32_LogicalDisk where DriveType = '3'")
        Dim str1 As String = ""
        Dim str2 As String = ""
        Dim str3 As String = ""
        Dim threadCount As Integer = 0
        Dim processCount As Integer = 0
        Dim uptime As String
        Dim localTime As String
        Dim myCollection As System.Management.ManagementObjectCollection
        Dim wmiObj As System.Management.ManagementObject
        Dim objPC As PerformanceCounter

        returner = System.Environment.MachineName
        myCollection = searchCS.Get()
        For Each wmiObj In myCollection
            returner = returner & "::" & wmiObj.GetPropertyValue("Status").ToString.Trim()
            returner = returner & "::" & wmiObj.GetPropertyValue("Manufacturer").ToString.Trim()
            returner = returner & "::" & wmiObj.GetPropertyValue("Model").ToString.Trim()
            returner = returner & "::" & wmiObj.GetPropertyValue("ThermalState").ToString.Trim()
            returner = returner & "::" & wmiObj.GetPropertyValue("SystemType").ToString.Trim()
            returner = returner & "::" & wmiObj.GetPropertyValue("NumberOfProcessors").ToString.Trim()
            returner = returner & "::" & wmiObj.GetPropertyValue("UserName").ToString.Trim().ToUpper()
        Next

        myCollection = searchSE.Get()
        For Each wmiObj In myCollection
            returner = returner & "::" & wmiObj.GetPropertyValue("SerialNumber").ToString.Trim().ToUpper()
        Next

        myCollection = searchOS.Get()
        For Each wmiObj In myCollection
            returner = returner & "::" & wmiObj.GetPropertyValue("Caption").ToString.Trim() & " " & wmiObj.GetPropertyValue("CSDVersion").ToString.Trim()
            returner = returner & "::" & wmiObj.GetPropertyValue("FreePhysicalMemory").ToString.Trim()
            returner = returner & "::" & wmiObj.GetPropertyValue("TotalVisibleMemorySize").ToString.Trim()
            returner = returner & "::" & wmiObj.GetPropertyValue("Version").ToString.Trim()
        Next

        'uptime
        myCollection = searchUpTime.Get()
        For Each wmiObj In myCollection
            uptime = wmiObj.GetPropertyValue("SystemUpTime").ToString.Trim()
            localTime = wmiObj.GetPropertyValue("Timestamp_Object").ToString.Trim()
            str1 = wmiObj.GetPropertyValue("Frequency_Object").ToString.Trim()
            str1 = ((Double.Parse(localTime) - Double.Parse(uptime)) / Double.Parse(str1)) / (3600)
            If CType((str1 / 24), Integer) < 10 Then
                str2 = "0" & CType((str1 / 24), Integer).ToString
            Else
                str2 = CType((str1 / 24), Integer).ToString
            End If
            If CType((str1 Mod 24), Integer) < 10 Then
                str2 = str2 & "d 0" & CType((str1 Mod 24), Integer) & "h"
            Else
                str2 = str2 & "d " & CType((str1 Mod 24), Integer) & "h"
            End If
            returner = returner & "::" & str2
            str1 = ""
            str2 = ""
        Next

        myCollection = searchHD.Get()
        For Each wmiObj In myCollection
            If str1 = "" Then
                str1 = wmiObj.GetPropertyValue("Name").ToString.Trim.Replace(":", "")
                str2 = CType((wmiObj.GetPropertyValue("FreeSpace").ToString.Trim() / wmiObj.GetPropertyValue("Size").ToString.Trim()) * 100, Integer).ToString
                str3 = CType((wmiObj.GetPropertyValue("FreeSpace").ToString.Trim() / (2 ^ 20)), Integer).ToString
            Else
                str1 = str1 & ":" & wmiObj.GetPropertyValue("Name").ToString.Trim.Replace(":", "")
                str2 = str2 & ":" & CType((wmiObj.GetPropertyValue("FreeSpace").ToString.Trim() / wmiObj.GetPropertyValue("Size").ToString.Trim()) * 100, Integer).ToString
                str3 = str3 & ":" & CType((wmiObj.GetPropertyValue("FreeSpace").ToString.Trim() / (2 ^ 20)), Integer).ToString
            End If
        Next
        returner = returner & "::" & str1 & "::" & str2 & "::" & str3

        str1 = ""
        str2 = ""
        myCollection = searchCPU.Get()
        For Each wmiObj In myCollection
            If str1 = "" Then
                str1 = wmiObj.GetPropertyValue("Name").ToString.Trim()
                str2 = wmiObj.GetPropertyValue("MaxClockSpeed").ToString.Trim()
            Else
                str1 = str1 & ":" & wmiObj.GetPropertyValue("Name").ToString.Trim()
                str2 = str2 & ":" & wmiObj.GetPropertyValue("MaxClockSpeed").ToString.Trim()
            End If
        Next
        returner = returner & "::" & str1 & "::" & str2

        myCollection = searchP.Get()
        For Each wmiObj In myCollection
            If wmiObj.GetPropertyValue("ProcessID") > 0 Then
                processCount = processCount + 1
                threadCount = threadCount + wmiObj.GetPropertyValue("ThreadCount")
            End If
        Next
        returner = returner & "::" & processCount.ToString & "::" & threadCount.ToString

        objPC = New PerformanceCounter("System", "System Up Time")
        objPC.NextValue()
        returner = returner & "::" & clientGUID & "::" & objPC.NextValue
        'clientversion is (23)
        returner = returner & "::" & ernClientVersion
        'is worksation locked? (24)
        If workstationISLocked() Then
            returner = returner & "::" & "Locked"
        Else
            returner = returner & "::" & "Unlocked"
        End If

        Return returner
    End Function

    Private Sub tmrRebootReminder_Tick(ByVal state As Object)
        If Not rebootReminderActive Then showRebootReminder()
        If clientState.policy.rebootPolicy.rebootSchedule = rebootScheduleType.threeTimesADay Then
            System.Threading.Thread.Sleep(60000)
        End If
        setRebootReminder()
        'Dim d As Date
        'Dim c As Date
        'd = clientState.policy.rebootPolicy.time1.AddDays(1)
        'c = Date.Parse("7/5/2007 " & Now.Hour & ":" & Now.Minute)
        'MsgBox((d - c).TotalMilliseconds)
    End Sub

    Private Sub showRebootReminder()
        rebootReminderActive = True
        If MsgBox("Changes have been made that require you to restart your computer.  Please do so as soon as possible.") = MsgBoxResult.Ok Then
            rebootReminderActive = False
        End If
    End Sub

    Private Sub showScheduledRebootReminder()
        MsgBox("Don't forget, your computer needs to be restarted.  Please do so as soon as possible.")
    End Sub

    Private Sub autoUpdateClient(ByVal info() As String)
        Dim proc As Process
        Dim auType As String
        Dim auName As String = ""

        auType = System.IO.Path.GetExtension(info(0))
        Select Case auType.ToLower
            Case ".zip"
                Dim unzip As New ZipHelper

                unzip.ExtractFilesFromZip(filesLocationDownloads & info(0), filesLocationDownloads & "\au", "")
                'update adds line into au.log with results:
                '(0|1):(date installed):(<last version>):(autoupdate id):(#>=0):<text>
                '1 = success   0 = failure
                'date installed
                'updating from version X
                'au id
                'specific return code (already updated, missing files, updated but other problems
                'text explaining return code
                'update then runs ern.exe
                If IO.File.Exists(filesLocationDownloads & "au\auEngine.exe") Then
                    auName = filesLocationDownloads & "au\auEngine.exe"
                ElseIf IO.File.Exists(filesLocationDownloads & "au\au.exe") Then
                    auName = filesLocationDownloads & "au\au.exe"
                ElseIf IO.File.Exists(filesLocationDownloads & "au\update.exe") Then
                    auName = filesLocationDownloads & "au\update.exe"
                ElseIf IO.File.Exists(filesLocationDownloads & "au\install.exe") Then
                    auName = filesLocationDownloads & "au\install.exe"
                ElseIf IO.File.Exists(filesLocationDownloads & "au\setup.exe") Then
                    auName = filesLocationDownloads & "au\setup.exe"
                Else
                End If
            Case ".exe"
                auName = filesLocationDownloads & info(0)
            Case Else
                'log invalid update attempt
        End Select

        If auName <> "" Then
            proc = System.Diagnostics.Process.Start(auName, "-l=" & ControlChars.Quote & Application.StartupPath & ControlChars.Quote & " -v=" & ernClientVersion & " -i=" & info(3) & " -p=" & Diagnostics.Process.GetCurrentProcess.Id)
            proc.WaitForExit()
        End If

        'ON STARTUP - ERN server tells ERN client what the client version was before
        '             if different then check au.log and send the server the info
    End Sub

    Private Sub cleanupWorkingDirectories()
        Dim workingDir As IO.DirectoryInfo

        If IO.Directory.Exists(filesLocationDownloads) Then
            workingDir = New IO.DirectoryInfo(filesLocationDownloads)
            workingDir.Delete(True)
        End If

        IO.Directory.CreateDirectory(filesLocationDownloads)
    End Sub

    Function workstationISLocked() As Boolean
        Dim p_lngHwnd As Int32
        Dim p_lngRtn As Int32
        Dim p_lngErr As Int32

        p_lngHwnd = OpenDesktop("Default", 0, False, DESKTOP_SWITCHDESKTOP)
        p_lngRtn = SwitchDesktop(hDesktop:=p_lngHwnd)
        p_lngErr = Err.LastDllError
        If p_lngRtn = 0 Then
            If p_lngErr = 0 Then
                'desktop is locked
                p_lngHwnd = CloseDesktop(p_lngHwnd)
                workstationISLocked = True
            Else
                p_lngHwnd = CloseDesktop(p_lngHwnd)
                workstationISLocked = False
            End If
        Else
            p_lngHwnd = CloseDesktop(p_lngHwnd)
            workstationISLocked = False
        End If
    End Function

    Private Sub iconSystray_MouseDoubleClick(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles iconSystray.MouseDoubleClick
        frmUI.WindowState = FormWindowState.Normal
        frmUI.Show()
        frmUI.lblClientVersion.Text = ernClientVersion
        frmUI.lblLastCheckedInTime.Text = lastCheckInTime
        frmUI.Activate()
    End Sub
End Class
